package ldh.fx.adminfx.util;

import javafx.fxml.FXMLLoader;
import javafx.geometry.NodeOrientation;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import ldh.fx.adminfx.pojo.FxmlBean;
import org.kordamp.ikonli.javafx.FontIcon;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class RegionUtil {

    private final static Logger LOGGER = LoggerUtil.getFileLogger(RegionUtil.class);

    public static Node copyGraphic(Node node) {
        if (node == null) return null;
        if (node instanceof FontIcon) {
            FontIcon fontIcon = (FontIcon) node;
            if (fontIcon.getIconCode() != null) {
                return FontIcon.of(((FontIcon) node).getIconCode());
            }
        }
        return null;
    }

    public static void loadFxml(Pane pane, Object controller, String urlFxml) {
        FXMLLoader fxmlLoader = new FXMLLoader(RegionUtil.class.getResource(urlFxml));
        fxmlLoader.setController(controller);
        fxmlLoader.setRoot(pane);
        try {
            fxmlLoader.load();
        } catch (IOException exception) {
            LOGGER.log(Level.SEVERE, "loadFxml error", exception);
            throw new RuntimeException(exception);
        }
    }

    public static <T> T loadFxml(String urlFxml) {
        FXMLLoader fxmlLoader = new FXMLLoader(RegionUtil.class.getResource(urlFxml));
        try {
            return fxmlLoader.load();
        } catch (IOException exception) {
            LOGGER.log(Level.SEVERE, "loadFxml error", exception);
            throw new RuntimeException(exception);
        }
    }

    public static <N, T> FxmlBean<N, T> loadFxmlBean(String urlFxml) {
        FXMLLoader fxmlLoader = new FXMLLoader(RegionUtil.class.getResource(urlFxml));
        try {
            N t = fxmlLoader.load();
            T t1 = fxmlLoader.getController();
            return new FxmlBean(t1, t);
        } catch (IOException exception) {
            LOGGER.log(Level.SEVERE, "loadFxmlBean error", exception);
            throw new RuntimeException(exception);
        }
    }

    public static void sizeRegion(Region region, Scene scene) {
        region.setPrefWidth(scene.getWidth());
        region.setPrefHeight(scene.getHeight());
//        region.resize(scene.getWidth(), scene.getHeight());
        region.requestLayout();
    }

    public static void sizeRegionWhenSceneChange(Region region, Scene scene) {
        scene.widthProperty().addListener((l, o, n)-> RegionUtil.sizeRegion(region, scene));
        scene.heightProperty().addListener((l, o, n)->RegionUtil.sizeRegion(region, scene));
    }

    public static Double anchorY(Region node, PopupPos popupPos) {
        double anchorY = node.getScene().getWindow().getY() + node.localToScene(0, 0).getY() + node.getScene().getY();
        if (popupPos == PopupPos.down_east) {
            anchorY = anchorY + node.getHeight();
        } else if (popupPos == PopupPos.down_west) {
            anchorY = anchorY + node.getHeight();
        } else if (popupPos == PopupPos.up_east) {
            anchorY = anchorY - node.getHeight();
        } else if (popupPos ==PopupPos.up_west) {
            anchorY = anchorY - node.getHeight();
        }
        return anchorY;
    }

    public static Double anchorX(Region node, PopupPos popupPos) {
        double anchorX = node.getScene().getWindow().getX() + node.localToScene(0, 0).getX() + node.getScene().getX() - 1;
        if (popupPos == PopupPos.down_east) {
            anchorX = anchorX + node.getHeight();
        } else if (popupPos == PopupPos.down_west) {
            anchorX = anchorX + node.getHeight();
        } else if (popupPos == PopupPos.up_east) {
            anchorX = anchorX - node.getWidth();
        } else if (popupPos == PopupPos.up_west) {
            anchorX = anchorX - node.getWidth();
        }
        return anchorX;
    }

    public static Double anchorX(Region node) {
        double anchorX = node.getScene().getWindow().getX() + node.localToScene(0, 0).getX() + node.getScene().getX();
        return anchorX;
    }

    public static Double anchorY(Region node) {
        double anchorY = node.getScene().getWindow().getY() + node.localToScene(0, 0).getY() + node.getScene().getY();
        return anchorY;
    }

    public static double calcAnchorX(Region region, PopupPos popupPos, Node contentPane) {
        double anchorX = region.getScene().getWindow().getX() + region.localToScene(0, 0).getX() + region.getScene().getX();
        double width = popupContentWidth(contentPane);

        if (region.getParent() != null && region.getParent().getNodeOrientation() == NodeOrientation.RIGHT_TO_LEFT) {
            if (popupPos == PopupPos.down_east) {
                anchorX = anchorX + region.getWidth() - popupContentWidth(contentPane);
            } else if (popupPos == PopupPos.down_west) {
                anchorX = anchorX - width;
            } else if (popupPos == PopupPos.up_east) {
                anchorX = anchorX + region.getWidth() - popupContentWidth(contentPane);
            } else if (popupPos == PopupPos.up_west) {
                anchorX = anchorX - width;
            }
        } else {
            if (popupPos == PopupPos.down_east) {
//            anchorX = anchorX + region.getWidth() - popupContentWidth(contentPane);
            } else if (popupPos == PopupPos.down_west) {
                anchorX = anchorX + region.getWidth() - width;
            } else if (popupPos == PopupPos.up_east) {
//            anchorX = anchorX - popupContentWidth(contentPane);
            } else if (popupPos == PopupPos.up_west) {
                anchorX = anchorX - width;
            }
        }

        System.out.println("widht:" + width + ", rrwww:" + region.getWidth() + ", xx:" + anchorX);
        return anchorX;
    }

    public static double calcAnchorY(Region region, PopupPos popupPos, Node contentPane) {
        double anchorY = region.getScene().getWindow().getY() + region.localToScene(0, 0).getY() + region.getScene().getY();
        if (popupPos == PopupPos.down_east) {
            anchorY = anchorY + region.getHeight() + 1;
        } else if (popupPos == PopupPos.down_west) {
            anchorY = anchorY + region.getHeight() + 1;
        } else if (popupPos == PopupPos.up_east) {
            anchorY = anchorY - popupContentHeight(contentPane) - 1;
        } else if (popupPos == PopupPos.up_west) {
            anchorY = anchorY - popupContentHeight(contentPane) - 1;
        }
        return anchorY;
    }

    public static double snapSize(Region region, double value) {
        return snapSize(value, region.isSnapToPixel());
    }

    private static double popupContentWidth(Node contentPane) {
        if (contentPane instanceof Region) {
            Region r = (Region) contentPane;
            return r.getWidth();
        }
        return contentPane.prefWidth(0);
    }

    private static double popupContentHeight(Node contentPane) {
        if (contentPane instanceof Region) {
            Region r = (Region) contentPane;
            return r.getHeight();
        }
        return contentPane.prefHeight(0);
    }

    private static double snapSize(double value, boolean snapToPixel) {
        return snapToPixel ? Math.ceil(value) : value;
    }

    public static double calcStringHeight(String str, double width) {
        Text textHolder = new Text();
        textHolder.setWrappingWidth(width);
        textHolder.setText(str);
        double h = textHolder.layoutBoundsProperty().get().getHeight();
        return h;
    }

    public static double calcStringHeight(String str, double width, Font font) {
        Text textHolder = new Text();
        textHolder.setWrappingWidth(width);
        textHolder.setText(str);
        textHolder.setFont(font);
        double h = textHolder.layoutBoundsProperty().get().getHeight();
        return h;
    }

    public static double calcStringWidth(String str) {
        Text textHolder = new Text();
//        textHolder.setWrappingWidth(width);
        textHolder.setText(str);
        double h = textHolder.layoutBoundsProperty().get().getWidth();
        return h;
    }

    public static double calcStringWidth(String str, Font font) {
        Text textHolder = new Text();
//        textHolder.setWrappingWidth(width);
        textHolder.setText(str);
        textHolder.setFont(font);
        double h = textHolder.layoutBoundsProperty().get().getHeight();
        return h;
    }
}
